package com.estate.web.controller.system;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.estate.common.annotation.Log;
import com.estate.common.constant.UserConstants;
import com.estate.common.core.controller.BaseController;
import com.estate.common.core.domain.AjaxResult;
import com.estate.common.core.domain.entity.SysUser;
import com.estate.common.core.domain.model.LoginUser;
import com.estate.common.core.domain.req.SysUserAddReq;
import com.estate.common.core.domain.req.SysUserEditReq;
import com.estate.common.core.domain.req.SysUserUpdateProfileReq;
import com.estate.common.core.domain.req.SysUserUpdatePwdReq;
import com.estate.common.core.domain.resp.SysUserResp;
import com.estate.common.core.page.TableDataInfo;
import com.estate.common.enums.BusinessType;
import com.estate.common.utils.DateUtils;
import com.estate.common.utils.SecurityUtils;
import com.estate.common.utils.StringUtils;
import com.estate.common.utils.bean.BeanUtils;
import com.estate.framework.web.service.TokenService;
import com.estate.system.service.ISysDeptService;
import com.estate.system.service.ISysRoleService;
import com.estate.system.service.ISysUserService;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

/**
 * 用户信息
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/system/user")
public class SysUserController extends BaseController
{
    @Autowired
    private ISysUserService userService;

    @Autowired
    private ISysRoleService roleService;

    @Autowired
    private ISysDeptService deptService;

    @Autowired
    private TokenService tokenService;

    /**
     * 获取用户列表
     */
    @GetMapping("/list")
    public TableDataInfo list(SysUser user)
    {
        startPage();
        Page<SysUser> list = userService.selectUserPage(user);
        return getDataTable(list, SysUserResp.class);
    }

    /**
     * 根据用户编号获取详细信息
     */
    @GetMapping(value = "/{userId}")
    public AjaxResult getInfo(@PathVariable(value = "userId") Long userId)
    {
        userService.checkUserDataScope(userId);
        SysUser sysUser = userService.selectUserById(userId);
        return success(sysUser, SysUserResp.class);
    }

    /**
     * 新增用户
     */
    @Log(title = "User Management", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody SysUserAddReq req)
    {
        if (StringUtils.isEmpty(req.getPassword())) {
            return error("Failed to add user " + req.getUserName() + ", password cannot be empty");
        }
        SysUser user = new SysUser();
        BeanUtils.copyBeanProp(user, req);
        user.setUserName(req.getEmail());
        user.setRoleIds(new Long[]{req.getRoleId()});
        deptService.checkDeptDataScope(user.getDeptId(), user.getTeamId());
        roleService.checkRoleDataScope(user.getRoleIds());
        if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
        {
            return error("Failed to add user " + req.getUserName() + ", email account already exists");
        } else if (!userService.checkUserNameUnique(user))
        {
            return error("Failed to add user " + req.getUserName() + ", username already exists");
        }
        user.setCreateBy(getUsername());
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        return toAjax(userService.insertUser(user));
    }

    /**
     * 修改用户
     */
    @Log(title = "User Management", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody SysUserEditReq req)
    {
        SysUser user = new SysUser();
        BeanUtils.copyBeanProp(user, req);
        user.setUserName(req.getEmail());
        user.setRoleIds(new Long[]{req.getRoleId()});
        userService.checkUserAllowed(user);
        userService.checkUserDataScope(user.getUserId());
        deptService.checkDeptDataScope(user.getDeptId());
        roleService.checkRoleDataScope(user.getRoleIds());
        if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
        {
            return error("Failed to update user " + req.getUserName() + ", email account already exists");
        } else if (!userService.checkUserNameUnique(user))
        {
            return error("Failed to update user " + req.getUserName() + ", username already exists");
        }
        user.setUpdateBy(getUsername());
        if (StringUtils.isNotBlank(user.getPassword())) {
            user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        }
        return toAjax(userService.updateUser(user));
    }

    /**
     * 修改密码
     * @param req
     * @return
     */
    @Log(title = "User Management", businessType = BusinessType.UPDATE)
    @PutMapping("/pwd")
    public AjaxResult updatePwd(@Validated @RequestBody SysUserUpdatePwdReq req)
    {
        SysUser user = new SysUser();
        user.setUserId(req.getUserId());
        userService.checkUserAllowed(user);
        userService.checkUserDataScope(req.getUserId());

        SysUser sysUser = userService.selectUserById(req.getUserId());
        String password = sysUser.getPassword();
        String oldPassword = req.getOldPassword();
        String newPassword = req.getNewPassword();
        if (!SecurityUtils.matchesPassword(oldPassword, password))
        {
            return error("Password change failed. The old password is incorrect.");
        }
        if (SecurityUtils.matchesPassword(newPassword, password))
        {
            return error("The new password cannot be the same as the old password.");
        }
        if (newPassword.length() < UserConstants.PASSWORD_MIN_LENGTH
                || newPassword.length() > UserConstants.PASSWORD_MAX_LENGTH)
        {
            return error("Password length must be between 5 and 20 characters.");
        }
        newPassword = SecurityUtils.encryptPassword(newPassword);
        user.setPassword(newPassword);
        return toAjax(userService.updateUserProfile(user));
    }

    /**
     * 修改个人信息
     */
    @Log(title = "User Management", businessType = BusinessType.UPDATE)
    @PutMapping("/profile")
    public AjaxResult updateProfile(@RequestBody SysUserUpdateProfileReq req)
    {
        LoginUser loginUser = getLoginUser();
        SysUser user = new SysUser();
        BeanUtils.copyBeanProp(user, req);
        user.setUserId(loginUser.getUserId());
        if (StringUtils.isNotEmpty(user.getEmail()))
        {
            if (!userService.checkEmailUnique(user)) {
                return error("Failed to update user profile, email account already exists");
            }
            else if (!userService.checkUserNameUnique(user))
            {
                return error("Failed to update user profile, username already exists");
            }
            user.setUserName(req.getEmail().trim());
        }

        // 修改密码
        String oldPassword = req.getOldPassword();
        String newPassword = req.getNewPassword();
        String password = loginUser.getPassword();
        if (StringUtils.isNotEmpty(oldPassword) && StringUtils.isNotEmpty(newPassword)) {
            if (!SecurityUtils.matchesPassword(oldPassword, password))
            {
                return error("Password change failed. The old password is incorrect.");
            }
            if (SecurityUtils.matchesPassword(newPassword, password))
            {
                return error("The new password cannot be the same as the old password.");
            }
            if (newPassword.length() < UserConstants.PASSWORD_MIN_LENGTH
                    || newPassword.length() > UserConstants.PASSWORD_MAX_LENGTH)
            {
                return error("Password length must be between 5 and 20 characters.");
            }

            newPassword = SecurityUtils.encryptPassword(newPassword);
            user.setPassword(newPassword);
            // 更新缓存用户密码&密码最后更新时间
            loginUser.getUser().setPwdUpdateDate(DateUtils.getNowDate());
            loginUser.getUser().setPassword(newPassword);
        }
        String avatar = req.getAvatar();
        if (StringUtils.isNotEmpty(avatar)) {
            user.setAvatar(avatar);
        }
        if (userService.updateUserProfile(user) > 0) {
            tokenService.setLoginUser(loginUser);
        }
        return success();
    }

    /**
     * 删除用户
     */
    @Log(title = "User Management", businessType = BusinessType.DELETE)
    @DeleteMapping("/{userIds}")
    public AjaxResult remove(@PathVariable Long[] userIds)
    {
        if (ArrayUtils.contains(userIds, getUserId()))
        {
            return error("Current user cannot be deleted");
        }
        return toAjax(userService.deleteUserByIds(userIds));
    }
}
